﻿using QuickJS.Native;
using QuickJS;
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace TTRom
{
    //quickjs 性能比JINT好多了，部署稍微麻烦。
    //好处是其不含JIT，容易部署
    //移植到Unity也是比较容易的
    public class JsBind : IDisposable
    {
        QuickJS.QuickJSRuntime jsruntime;
        QuickJS.QuickJSContext jscontext;
        IRomRuntime runtime;
        public JsBind(IRomRuntime runtime)
        {
            this.runtime = runtime;
            jsruntime = new QuickJS.QuickJSRuntime();
            jscontext = new QuickJS.QuickJSContext(jsruntime);
            this.Bind();
        }
        void Bind()
        {
            QuickJSValue ttname = QuickJSValue.Create(jscontext, JSClassID.Object);
            jscontext.GetGlobal().DefineProperty("tt", ttname, JSPropertyFlags.Normal);
            //can gen this
            ttname.DefineFunction("GetEnvString", __GetEnvString, 0, JSPropertyFlags.Normal);
            ttname.DefineFunction("Init", __Init, 2, JSPropertyFlags.Normal);
        }
        //can gen this.
        public JSValue __GetEnvString(JSContext ctx, [In] JSValue this_val, int argc, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] JSValue[] argv)
        {
            //1.参数检查与转换

            //2.调用实际代码
            var ret = this.runtime.GetEnvString();

            //3.转换返回值
            return JSValue.Create(ctx, ret);
        }
        QuickJSValue onUpdate;
        QuickJSValue onInit;
        public JSValue __Init(JSContext ctx, [In] JSValue this_val, int argc, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] JSValue[] argv)
        {
            //1.参数检查与转换
            if (argv[0].IsFunction(ctx) == false)
                throw new Exception("error arg");
            var ret = this.runtime.GetEnvString();

            onInit = QuickJSValue.Wrap(jscontext, argv[0]);
            onUpdate = QuickJSValue.Wrap(jscontext, argv[1]);
            //2.调用实际代码
            this.runtime.Init((sysinfo) =>
            {
                var v=
                //2.5 回调处理,这里参数没转
                onInit.Call(JSValue.Undefined, JSValue.Create(1));
            },(updateinfo)=>
            {
                //2.5 回调处理,这里参数没转
                var r = onUpdate.Call(JSValue.Undefined, JSValue.Create(1));
                //返回值也没转
                return r as ICommandBuffer;
            });

            //3.转换返回值
            return JSValue.Undefined;
        }

        public void Dispose()
        {
            jscontext.Dispose();
            jsruntime.Dispose();
        }
    }
}
